package com.kinghood.productcenter.service.product.handler;

import com.kinghood.infrastructure.model.KingHoodExceptionUtil;
import com.kinghood.infrastructure.util.base.IdGenUtil;
import com.kinghood.productcenter.common.model.dao.base.BaseAttributeDO;
import com.kinghood.productcenter.common.model.dao.base.BaseAttributeLimitDO;
import com.kinghood.productcenter.common.model.dao.base.BaseAttributeValueDO;
import com.kinghood.productcenter.common.model.dao.product.*;
import com.kinghood.productcenter.common.model.dto.product.*;
import com.kinghood.productcenter.common.model.enums.product.ProductSkuStatusEnums;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author zhangFanJun
 * @date 2024-01-26 15:43
 **/
@Slf4j
public class ProductSkuBaseHandler {


    /**
     * 检查表头
     * */
    public static Map<Integer, ProductExcelAttributeDTO> checkExcelHead(Map<Integer, String> dataMap, BaseProductDaoDTO dao) {

        Collection<String> values = dataMap.values().stream().map(ProductBaseHandler::handleValueParam)
                .filter(Objects::nonNull).collect(Collectors.toList());
        HashMap<String, String> sysMap = new HashMap<>();
        sysMap.put("款号", "styleNumber");
        sysMap.put("SKU编码", "skuCode");
        sysMap.put("SKU状态", "skuStatus");
        sysMap.put("供应商", "supplier");

        List<String> match = Arrays.asList("款号", "SKU编码");
        boolean flag = match.stream().allMatch(values::contains);
        KingHoodExceptionUtil.trueThrows(!flag, match.toString() + "都是必填的");

        HashMap<Integer, ProductExcelAttributeDTO> fieldMap = new HashMap<>();
        dataMap.forEach((key, value) -> {
            // 去掉*
            value = ProductBaseHandler.handleValueParam(value);
            if(StringUtils.isEmpty(value)){
                return;
            }
            ProductExcelAttributeDTO a = new ProductExcelAttributeDTO();
            a.setValue(value);
            fieldMap.put(key, a);

            String code = sysMap.get(value);
            if (Objects.nonNull(code)) {
                a.setIsAttribute(false);
                a.setCode(code);
                return;
            }
            BaseAttributeDO baseAttributeDO = dao.getAttributeMap().get(value);
            if (Objects.isNull(baseAttributeDO)) {
                KingHoodExceptionUtil.isNull(baseAttributeDO, "属性【" + value + "】不支持");
            }
            a.setIsAttribute(true);
            a.setAttributeCode(baseAttributeDO.getAttributeCode());
            a.setAttributeName(baseAttributeDO.getAttributeName());
            a.setAttributeId(baseAttributeDO.getId());
            a.setValueType(baseAttributeDO.getValueType());
            a.setValueCode(baseAttributeDO.getValueCode());
            a.setIsMultipleChoice(baseAttributeDO.getIsMultipleChoice());
            BaseAttributeLimitDO attributeLimitDO = dao.getAttributeLimitMap().get(baseAttributeDO.getId());
            a.setAttributeLimit(attributeLimitDO);
            List<BaseAttributeValueDO> attributeValueDOList = dao.getAttributeValueMap().get(baseAttributeDO.getId());
            if (!CollectionUtils.isEmpty(attributeValueDOList)) {
                Map<String, BaseAttributeValueDO> attributeValueDOMap = attributeValueDOList.stream()
                        .collect(Collectors.toMap(BaseAttributeValueDO::getValue, v -> v, (k1, k2) -> k2));
                a.setAttributeValueMap(attributeValueDOMap);
            }
        });

        return fieldMap;
    }

    /**
     * 处理excel数据
     * */
    public static List<ProductExcelRowDTO> handleExcelData(List<Map<Integer, String>> cachedDataList, Map<Integer, ProductExcelAttributeDTO> headCodeMap, BaseProductDaoDTO dao, RowFieldRecordDTO rowFieldRecord){

        List<ProductExcelRowDTO> rowList = new ArrayList<>();
        for (int i = 0; i < cachedDataList.size(); i++) {
            Map<Integer, String> data = cachedDataList.get(i);
            AtomicBoolean bad = new AtomicBoolean(false);
            AtomicReference<String> message = new AtomicReference();
            Map<Integer, ExcelDataInfoDTO> map = new HashMap<>();
            ProductExcelRowDTO row = new ProductExcelRowDTO();
            row.setIndex(i);
            row.setMap(map);
            rowList.add(row);

            // 行数据解析
            data.forEach((key, value) -> {
                ProductExcelAttributeDTO code = headCodeMap.get(key);
                if(Objects.isNull(code)){
                    log.info("{}列因为没有标题不解析",key+1);
                    return;
                }
                ExcelDataInfoDTO one = new ExcelDataInfoDTO();
                one.setIndex(key);
                one.setValue(value);
                map.put(key, one);
                if (bad.get()) {
                    return;
                }

                // 属性
                if (Objects.equals(code.getIsAttribute(), Boolean.TRUE)) {
                    if (StringUtils.isEmpty(value)) {
                        return;
                    }
                    one.setAttributeId(code.getAttributeId());
                    one.setAttributeCode(code.getAttributeCode());
                    one.setAttributeName(code.getAttributeName());
                    one.setValueCode(code.getValueCode());
                    one.setValueType(code.getValueType());
                    one.setIsMultipleChoice(code.getIsMultipleChoice());
                    one.setAttributeLimit(code.getAttributeLimit());
                    one.setAttributeValueMap(code.getAttributeValueMap());
                }
                if (Objects.isNull(code.getCode())) {
                    return;
                }
                // 系统字段
                switch (code.getCode()) {
                    case "styleNumber":
                        one.setStyleNumber(value);
                        row.setStyleNumber(value);
                        if (StringUtils.isEmpty(value)) {
                            bad.set(true);
                            message.set("款号未填");
                        } else {
                            Long productId = dao.getStyleMap().get(value);
                            one.setProductId(productId);
                            row.setProductId(productId);
                            if (Objects.isNull(productId)) {
                                bad.set(true);
                                message.set("款号不存在");
                            }
                        }
                        break;
                    case "skuCode":
                        if (StringUtils.isEmpty(value)) {
                            break;
                        }
                        one.setSkuCode(value);
                        row.setSkuCode(value);
                        if (dao.getSkuCodeList().contains(value)) {
                            bad.set(true);
                            message.set("SKU编码已经存在");
                        }
                        break;
                    case "skuStatus":
                        if (StringUtils.isEmpty(value)) {
                            break;
                        }
                        Integer skuStatus = ProductSkuStatusEnums.getTypeByName(value);
                        one.setSkuStatus(skuStatus);
                        row.setSkuStatus(skuStatus);
                        if (Objects.isNull(skuStatus)) {
                            bad.set(true);
                            message.set("SKU状态填停用或者启用");
                        }
                        break;
                    case "supplier":
                        if (StringUtils.isEmpty(value)) {
                            break;
                        }
                        Long supplierId = dao.getSupplierMap().get(value);
                        one.setSupplierId(supplierId);
                        row.setSupplierId(supplierId);
                        if (Objects.isNull(supplierId)) {
                            bad.set(true);
                            message.set("供应商检查不通过");
                        }
                        break;
                    default:
                }
            });
            if(StringUtils.isEmpty(row.getStyleNumber())){
                bad.set(true);
                message.set("款号必填");
            }
            if(StringUtils.isEmpty(row.getSkuCode())){
                bad.set(true);
                message.set("sku编码必填");
            }
            if(StringUtils.isEmpty(row.getSkuStatus())){
                bad.set(true);
                message.set("sku状态未填");
            }
            if (bad.get()) {
                int size = rowFieldRecord.getSize();
                row.setBad(true);
                row.setBadMessage(message.get());
                ExcelDataInfoDTO one = new ExcelDataInfoDTO();
                one.setIndex(size);
                one.setValue("导入失败");
                one.setBad(true);
                map.put(size, one);
                ExcelDataInfoDTO two = new ExcelDataInfoDTO();
                two.setIndex(size + 1);
                two.setValue(message.get());
                two.setBad(true);
                map.put(size + 1, two);
            }
        }

        return rowList;
    }

    /**
     * 处理sku的数据
     * */
    public static ProductExcelDaoDTO handleProductSkuData(List<ProductExcelRowDTO> list, RowFieldRecordDTO rowFieldRecord, BaseProductDaoDTO dao) {

        ProductExcelDaoDTO res = new ProductExcelDaoDTO();

        // 检查数据是否出现不一致的情况
        boolean bad = ProductBaseHandler.checkSameData(list, rowFieldRecord, dao);
        // 收集sku编码
        List<String> addList = list.stream().map(x -> {
            ExcelDataInfoDTO index = x.getMap().get(rowFieldRecord.getSkuStart());
            if (Objects.nonNull(index)) {
                return index.getValue();
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        dao.getSkuCodeList().addAll(addList);

        // 当有一个坏数据，整个失效
        if (bad) {
            String message = list.stream()
                    .filter(ProductExcelRowDTO::isBad)
                    .map(ProductExcelRowDTO::getBadMessage)
                    .findFirst().orElse(null);
            list.forEach(x -> {
                if (!x.isBad()) {
                    ProductBaseHandler.badData(x, message,rowFieldRecord.getSize());
                }
            });
            return null;
        } else {
            list.forEach(x -> {
                if (!x.isBad()) {
                    x.setSuccess(true);
                    int size = rowFieldRecord.getSize();
                    ExcelDataInfoDTO one = new ExcelDataInfoDTO();
                    one.setIndex(size);
                    one.setValue("导入成功");
                    x.getMap().put(size, one);
                }
            });
        }

        LocalDateTime now = LocalDateTime.now();
        ProductBaseDO productBaseDO = res.getProductBaseDO();
        List<ProductAttributeDO> attributes = res.getAttributes();
        List<ProductSkuBaseDO> skuBaseList = res.getSkuBaseList();
        List<ProductSkuSupplierBaseDO> supplierBaseList = res.getSupplierBaseList();
        List<ProductSkuExtrasBaseDO> extrasBaseList = res.getExtrasBaseList();

        // 商品
        ProductExcelRowDTO first = list.get(0);
        productBaseDO.setId(first.getProductId());
        productBaseDO.setStyleNumber(first.getStyleNumber());
        KingHoodExceptionUtil.isNull(productBaseDO.getId(),"款号id不存在");

        Map<String, ProductExcelRowDTO> skuMap = list.stream()
                .filter(x->Objects.nonNull(x.getSkuCode()))
                .collect(Collectors.toMap(k -> k.getStyleNumber() + k.getSkuCode(), v -> v, (k1, k2) -> k2));
        // sku
        for (ProductExcelRowDTO value : skuMap.values()) {
            if (StringUtils.isEmpty(value.getSkuCode())) {
                continue;
            }
            ProductSkuBaseDO skuBase = new ProductSkuBaseDO();
            skuBaseList.add(skuBase);
            skuBase.setId(IdGenUtil.getId());
            skuBase.setProductId(productBaseDO.getId());
            skuBase.setSkuUuid(skuBase.getId().toString());
            skuBase.setSkuCode(value.getSkuCode());
            skuBase.setSkuStatus(value.getSkuStatus());
            skuBase.setCreateTime(now);
            skuBase.setUpdateTime(now);
            skuBase.setCreateUserId(rowFieldRecord.getUserId());
            skuBase.setUpdateUserId(rowFieldRecord.getUserId());
            // sku属性
            for (int i = rowFieldRecord.getSkuStart(); i <= rowFieldRecord.getSkuEnd(); i++) {
                ExcelDataInfoDTO info = value.getMap().get(i);
                if (Objects.isNull(info) || Objects.isNull(info.getAttributeId()) || StringUtils.isEmpty(info.getValue())) {
                    continue;
                }
                ProductAttributeDO attribute = new ProductAttributeDO();
                attributes.add(attribute);
                attribute.setId(IdGenUtil.getId());
                attribute.setProductId(productBaseDO.getId());
                attribute.setBusinessId(skuBase.getId());
                attribute.setBusinessType(ProductAttributeDO.BUSINESS_TYPE_SKU);
                attribute.setAttributeId(info.getAttributeId());
                attribute.setAttributeCode(info.getAttributeCode());
                attribute.setValueType(info.getValueType());
                attribute.setValue(ProductBaseHandler.handleAttributeValue(info));
//                attribute.setValueFind(ProductBaseHandler.handleAttributeValueFind(info));
                attribute.setValueFind(attribute.getValue());
                attribute.setCreateTime(now);
                attribute.setUpdateTime(now);
                attribute.setCreateUserId(rowFieldRecord.getUserId());
                attribute.setUpdateUserId(rowFieldRecord.getUserId());
            }
        }

        Map<String, Long> skuIdMap = skuBaseList.stream().collect(Collectors.toMap(ProductSkuBaseDO::getSkuCode, ProductSkuBaseDO::getId, (k1, k2) -> k2));
        Map<String, ProductExcelRowDTO> supplier = list.stream()
                .filter(x->Objects.nonNull(x.getSupplierId()))
                .collect(Collectors.toMap(k -> k.getStyleNumber() + k.getSkuCode() + k.getSupplierId(), v -> v, (k1, k2) -> k2));
        // 供应商
        for (ProductExcelRowDTO value : supplier.values()) {
            if (Objects.isNull(value.getSupplierId())) {
                continue;
            }
            ProductSkuSupplierBaseDO supplierBase = new ProductSkuSupplierBaseDO();
            supplierBaseList.add(supplierBase);
            supplierBase.setId(IdGenUtil.getId());
            supplierBase.setProductId(productBaseDO.getId());
            supplierBase.setProductSkuId(skuIdMap.get(value.getSkuCode()));
            supplierBase.setSupplierId(value.getSupplierId());
            supplierBase.setCreateTime(now);
            supplierBase.setUpdateTime(now);
            supplierBase.setCreateUserId(rowFieldRecord.getUserId());
            supplierBase.setUpdateUserId(rowFieldRecord.getUserId());

            KingHoodExceptionUtil.isNull(supplierBase.getProductSkuId(),"供应商需要匹配sku");

            for (int i = rowFieldRecord.getSupplierStart(); i <= rowFieldRecord.getSupplierEnd(); i++) {
                ExcelDataInfoDTO info = value.getMap().get(i);
                // 下标不一定有值，excel在前面没有填的是null值，但是最后的列是完全没有值
                if (Objects.isNull(info) || Objects.isNull(info.getAttributeId()) || StringUtils.isEmpty(info.getValue())) {
                    continue;
                }
                ProductAttributeDO attribute = new ProductAttributeDO();
                attributes.add(attribute);
                attribute.setId(IdGenUtil.getId());
                attribute.setProductId(productBaseDO.getId());
                attribute.setBusinessId(supplierBase.getId());
                attribute.setBusinessType(ProductAttributeDO.BUSINESS_TYPE_SUPPLIER);
                attribute.setAttributeId(info.getAttributeId());
                attribute.setAttributeCode(info.getAttributeCode());
                attribute.setValueType(info.getValueType());
                attribute.setValue(ProductBaseHandler.handleAttributeValue(info));
//                attribute.setValueFind(ProductBaseHandler.handleAttributeValueFind(info));
                attribute.setValueFind(attribute.getValue());
                attribute.setCreateTime(now);
                attribute.setUpdateTime(now);
                attribute.setCreateUserId(rowFieldRecord.getUserId());
                attribute.setUpdateUserId(rowFieldRecord.getUserId());
            }
        }

        Map<String, ProductExcelRowDTO> extrasMap = list.stream()
                .filter(x->Objects.nonNull(x.getExtras()))
                .collect(Collectors.toMap(k -> k.getStyleNumber() + k.getSkuCode() + k.getExtras(), v -> v, (k1, k2) -> k2));
        // sku附件
        for (ProductExcelRowDTO value : extrasMap.values()) {
            if (StringUtils.isEmpty(value.getExtras())) {
                continue;
            }
            ProductSkuExtrasBaseDO extrasBase = new ProductSkuExtrasBaseDO();
            extrasBaseList.add(extrasBase);
            extrasBase.setId(IdGenUtil.getId());
            extrasBase.setProductId(productBaseDO.getId());
            extrasBase.setProductSkuId(skuIdMap.get(value.getSkuCode()));
            extrasBase.setCreateTime(now);
            extrasBase.setUpdateTime(now);
            extrasBase.setCreateUserId(rowFieldRecord.getUserId());
            extrasBase.setUpdateUserId(rowFieldRecord.getUserId());

            KingHoodExceptionUtil.isNull(extrasBase.getProductSkuId(),"附件需要匹配sku");

            for (int i = rowFieldRecord.getExtrasStart(); i <= rowFieldRecord.getExtrasEnd(); i++) {
                ExcelDataInfoDTO info = value.getMap().get(i);
                if (Objects.isNull(info.getAttributeId()) || StringUtils.isEmpty(info.getValue())) {
                    continue;
                }
                ProductAttributeDO attribute = new ProductAttributeDO();
                attributes.add(attribute);
                attribute.setId(IdGenUtil.getId());
                attribute.setProductId(productBaseDO.getId());
                attribute.setBusinessId(extrasBase.getId());
                attribute.setBusinessType(ProductAttributeDO.BUSINESS_TYPE_EXTRAS);
                attribute.setAttributeId(info.getAttributeId());
                attribute.setAttributeCode(info.getAttributeCode());
                attribute.setValueType(info.getValueType());
                attribute.setValue(ProductBaseHandler.handleAttributeValue(info));
//                attribute.setValueFind(ProductBaseHandler.handleAttributeValueFind(info));
                attribute.setValueFind(attribute.getValue());
                attribute.setCreateTime(now);
                attribute.setUpdateTime(now);
                attribute.setCreateUserId(rowFieldRecord.getUserId());
                attribute.setUpdateUserId(rowFieldRecord.getUserId());
            }
        }

        return res;
    }
}
